/**
 * @name: 格式化金钱
 * @description: 将字符串或数字修改格式为xxx,xxx,xxx
 * @param {number | string} num
 * @return: xxx,xxx,xxx
 */
export const ThousandNum = (num: number | string) => num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
/**
 * @name: 格式化金钱
 * @description: 将xxx,xxx,xxx修改格式数字
 * @param {string} val
 * @return: Number
 */
export const changeNumber = (val: string) => {
    if (val) {
        const a = `${val}`.replace(/,/g, '');
        return Number(a);
    }
    return 0;
};
/**
 * @name: 判断数据类型
 * @description: 判断数据类型是什么或者是否与传入类型一致
 * @param {any} tgt 要判断的参数
 * @param {string} type 要对比的类型
 * @return: boolean | string
 */
export const DataType = (tgt: any, type: string) => {
    const dataType = Object.prototype.toString
        .call(tgt)
        .replace(/\[object (\w+)\]/, '$1')
        .toLowerCase();
    return type ? dataType === type : dataType;
};
/**
 * @name: 是否为空数组
 * @description: 判断参数是否为数组并且为空
 * @param {any} arr 要判断的参数
 * @return: boolean
 */
export const isEmptyArr = (arr: any) => Array.isArray(arr) && !arr.length;
/**
 * @name: 是否为空对象
 * @description: 判断参数是否为对象并且为空对象
 * @param {any} obj 要判断的参数
 * @return: boolean
 */
export const isEmptyObj = (obj: any) => DataType(obj, 'object') && !Object.keys(obj).length;
/**
 * @name: 去重数组
 * @param {Array} arr 要去重的数组
 * @return: Array
 */
export const arrSet = (arr: any[]) => [...new Set([...arr])];
/**
 * @name: 过滤空值
 * @description: 过滤数组空值
 * @param {Array} arr 过滤数组空值
 * @return: Array
 */
export const arrFilterEmptyValue = (arr: any[]) => [...arr].filter(Boolean);

/**
 * @name: 构造树型结构数据
 * @param {Array<any>} data 数据源
 * @param {string} id id字段 默认 'id'
 * @param {string} name name字段 默认 'name'
 * @param {string} parentId 父节点字段 默认 'parentId'
 * @param {string} parentName
 * @param {string} children 子节点数据字段 默认 'children'
 */
export function buildTreeData(
    data: any[],
    id: string,
    name: string,
    parentId: string,
    parentName: string,
    children: string,
) {
    const config = {
        id: id || 'id',
        name: name || 'name',
        parentId: parentId || 'parentId',
        parentName: parentName || 'parentName',
        childrenList: children || 'children',
    };

    const childrenListMap = {};
    const nodeIds = {};
    const tree: any[] = [];
    data.forEach(
        (item: {
            id: string;
            name: string;
            key: string;
            title: string;
            value: any;
        }) => {
            const d = item;
            const pId = d[config.parentId];
            if (childrenListMap[pId] === null) {
                childrenListMap[pId] = [];
            }
            d.key = d[config.id];
            d.title = d[config.name];
            d.value = d[config.id];
            nodeIds[d[config.id]] = d;
            childrenListMap[pId].push(d);
        },
    );

    data.forEach((item: any) => {
        const d = item;
        const pId = d[config.parentId];
        if (nodeIds[pId] === null) {
            d[config.parentName] = '';
            tree.push(d);
        }
    });

    function adaptToChildrenList(item: any) {
        const o = item;
        if (childrenListMap[o[config.id]] !== null) {
            o[config.childrenList] = childrenListMap[o[config.id]];
        }
        if (o[config.childrenList]) {
            o[config.childrenList].forEach((child: any) => {
                const c = child;
                c[config.parentName] = o[config.name];
                adaptToChildrenList(c);
            });
        }
    }

    tree.forEach((t: any) => {
        adaptToChildrenList(t);
    });

    return tree;
}

/**
 * @name: 下载文件
 * @param {any} res 文件数据
 * @param {string} type 文件类型
 * @param {string} filename 文件名
 * @return: Array
 */
export const downloadFile = (res: any, type: string, filename: string) => {
    // 创建blob对象，解析流数据
    const blob = new Blob([res], {
        // 设置返回的文件类型
        // type: 'application/pdf;charset=UTF-8' 表示下载文档为pdf，如果是word则设置为msword，excel为excel
        type,
    });
    // 这里就是创建一个a标签，等下用来模拟点击事件
    const a = document.createElement('a');
    // 兼容webkix浏览器，处理webkit浏览器中href自动添加blob前缀，默认在浏览器打开而不是下载
    const URL = window.URL || window.webkitURL;
    // 根据解析后的blob对象创建URL 对象
    const herf = URL.createObjectURL(blob);
    // 下载链接
    a.href = herf;
    // 下载文件名,如果后端没有返回，可以自己写a.download = '文件.pdf'
    a.download = filename;
    document.body.appendChild(a);
    // 点击a标签，进行下载
    a.click();
    // 收尾工作，在内存中移除URL 对象
    document.body.removeChild(a);
    window.URL.revokeObjectURL(herf);
};
/**
 * @name: 引用数据类型深拷贝
 * @param {Object} source 原对象
 * @return: Object
 */
export const deepClone = (source: any) => {
    if (!source && typeof source !== 'object') {
        throw new Error('error arguments');
    }
    const targetObj = source.constructor === Array ? [] : {};
    Object.keys(source).forEach((keys: string | number) => {
        if (source[keys] && typeof source[keys] === 'object') {
            targetObj[keys] = deepClone(source[keys]);
        } else {
            targetObj[keys] = source[keys];
        }
    });
    return targetObj;
};
/**
 * @name: 删除对应键值对
 * @param {Object} params 原对象
 * @param {string[]} arrs 要删除的键
 * @return: Object
 */
export const deleteKeys = (params: any, arrs: string[]) => {
    const param = deepClone(params);
    // eslint-disable-next-line no-plusplus
    for (let i = 0; i <= arrs.length; i++) {
        Reflect.deleteProperty(param, arrs[i]);
    }
    return param;
};

/**
 * @name: 限制只能输入数字及小数点后两位
 * @description: 限制只能输入数字及小数点后两位
 * @param {string} str 输入值
 * @param {number} num 小数点前位数限制
 * @return string
 */
export const onlyNumberAndTwoDecimal = (str: string, num?: number) => {
    // eslint-disable-next-line no-param-reassign
    str = str.replace(/[^\d.]/g, '');
    // eslint-disable-next-line no-param-reassign
    str = str.replace(/^\./g, '');
    // eslint-disable-next-line no-param-reassign
    str = str.replace(/\.{2,}/g, '');
    // eslint-disable-next-line no-param-reassign
    str = str.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
    if (num) {
        // eslint-disable-next-line no-param-reassign
        str = str.indexOf('.') > 0
            ? `${str.split('.')[0].substring(0, num)}.${str
                .split('.')[1]
                .substring(0, 2)}`
            : str;
    } else {
        // eslint-disable-next-line no-param-reassign
        str = str.indexOf('.') > 0
            ? `${str.split('.')[0]}.${str.split('.')[1].substring(0, 2)}`
            : str;
    }

    if (str.length > 1 && str[0] === '0' && str[1] !== '.') {
        // eslint-disable-next-line no-param-reassign
        str = str.slice(0);
    }
    return str;
};
/**
 * @name: 格式化时间
 * @param {string} fmt 格式化模板
 * @param {Date} date 日期
 * @return string
 */
export const dateFormatMethod = (fmt: string, date: Date) => {
    let ret;
    const opt = {
        'Y+': date.getFullYear().toString(), // 年
        'M+': (date.getMonth() + 1).toString(), // 月
        'd+': date.getDate().toString(), // 日
        'D+': date.getDate().toString(), // 日
        'H+': date.getHours().toString(), // 时
        'm+': date.getMinutes().toString(), // 分
        's+': date.getSeconds().toString(), // 秒
        // 有其他格式化字符需求可以继续添加，必须转化成字符串
    };
    // eslint-disable-next-line guard-for-in,no-restricted-syntax
    for (const k in opt) {
        ret = new RegExp(`(${k})`).exec(fmt);
        if (ret) {
            // eslint-disable-next-line no-param-reassign
            fmt = fmt.replace(
                ret[1],
                ret[1].length === 1
                    ? opt[k as keyof typeof opt]
                    : opt[k as keyof typeof opt].padStart(ret[1].length, '0'),
            );
        }
    }
    return fmt;
};
/**
 * @name: 去除空格
 * @description: type: 1-所有空格 2-前后空格 3-前空格 4-后空格
 * @param {string} str
 * @param {1 | 2 | 3 | 4} type
 * @return string
 */
export const trim = (str: string, type: 1 | 2 | 3 | 4) => {
    // eslint-disable-next-line no-param-reassign
    type = type || 1;
    switch (type) {
        case 1:
            return str.replace(/\s+/g, '');
        case 2:
            return str.replace(/(^\s*)|(\s*$)/g, '');
        case 3:
            return str.replace(/(^\s*)/g, '');
        case 4:
            return str.replace(/(\s*$)/g, '');
        default:
            return str;
    }
};
/**
 * @name: 字符转换
 * @description: type: 1:首字母大写 2：首字母小写 3：大小写转换 4：全部大写 5：全部小写
 * @param {string} str
 * @param {1 | 2 | 3 | 4 | 5} type
 * @return string
 */
export const changeCase = (str: string, type: 1 | 2 | 3 | 4 | 5) => {
    // eslint-disable-next-line no-param-reassign
    type = type || 4;
    switch (type) {
        case 1:
            return str.replace(
                /\b\w+\b/g,
                (word) => word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase(),
            );
        case 2:
            return str.replace(
                /\b\w+\b/g,
                (word) => word.substring(0, 1).toLowerCase() + word.substring(1).toUpperCase(),
            );
        case 3:
            return str
                .split('')
                .map((word) => {
                    if (/[a-z]/.test(word)) {
                        return word.toUpperCase();
                    }
                    return word.toLowerCase();
                })
                .join('');
        case 4:
            return str.toUpperCase();
        case 5:
            return str.toLowerCase();
        default:
            return str;
    }
};

/**
 * 参数处理
 * @param {*} params  参数
 * @return {string}
 */
export function tansParams(params) {
    let result = ''
    for (const propName of Object.keys(params)) {
        const value = params[propName];
        var part = encodeURIComponent(propName) + "=";
        if (value !== null && value !== "" && typeof (value) !== "undefined") {
            if (typeof value === 'object') {
                for (const key of Object.keys(value)) {
                    if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
                        let params = propName + '[' + key + ']';
                        var subPart = encodeURIComponent(params) + "=";
                        result += subPart + encodeURIComponent(value[key]) + "&";
                    }
                }
            } else {
                result += part + encodeURIComponent(value) + "&";
            }
        }
    }
    return result
}